<template>
  <div class="demo-content">
    <h1>连接关系模型实现</h1>
    <section class="demo-text">
      <el-row>
        <el-col :span="18">
          <canvas id="c" width="1200" height="600" ref="canvas"></canvas>
        </el-col>
      </el-row>
      <h2>实现思路</h2>
      <p>在点类型中记录_sourcelist和_targetlist分别记录与该点关联的线，监听对象的移动事件，当移动时对这两个对象进行遍历，改变关联的线的位置属性，实现线跟随点移动</p>
      <h5>为点添加连线</h5>
      <img src="~@/imags/20191211348.png" alt>
      <h5>为点事件添加监听</h5>
      <img src="~@/imags/20191211350.png" alt>
      <p>对_sourcelist和_targetlist中的连线进行遍历，将元素当前中心点赋值给连线，更改连线的位置，并刷新画布</p>
      <h2>扩展</h2>
      <p>在实际应用中，应该在连线中记录相对关系，通过节点当前位置和相对关系计算出新的坐标，这样才能保证连线的端点位置可变化，
        <br>连线关系模型更加灵活
      </p>
      <p style="text-align:right;padding-right:60px">@王睿杰 2019.1.21</p>
    </section>
  </div>
</template>
<script>
import {fabric} from  "@/js/fabric";
export default {
  data() {
    return {
      __canvas: null
    };
  },
  mounted() {
    this.$nextTick(() => {
      var canvas = (this.__canvas = new fabric.Canvas("c", {
        selection: false
      }));
      fabric.Object.prototype.originX = fabric.Object.prototype.originY =
        "center";

      function makeCircle(left, top, line1, line2, line3, line4) {
        var c = new fabric['Circle']({
          left: left,
          top: top,
          strokeWidth: 5,
          radius: 12,
          fill: "#fff",
          stroke: "#666"
        });
        c.hasControls = false; //显示控件
        c.hasBorders = false; //显示控件标签
        c._sourcelist = [];
        c._targetlist = [];
        c.line1 = line1;
        c.line2 = line2;
        c.line3 = line3;
        c.line4 = line4;
        return c;
      }

      function makeLine(coords) {
        return new fabric.Line(coords, {
          fill: "red",
          stroke: "red",
          strokeWidth: 5,
          selectable: false,
          evented: false
        });
      }

      var line = makeLine([250, 125, 250, 175]),
        line2 = makeLine([250, 175, 250, 250]),
        line3 = makeLine([250, 250, 300, 350]),
        line4 = makeLine([250, 250, 200, 350]),
        line5 = makeLine([250, 175, 175, 225]),
        line6 = makeLine([250, 175, 325, 225]);
      function addline(source, target) {
        //定义新的连线
        let line = makeLine([source.left, source.top, target.left, target.top]);
        line._source = source;
        line._target = target;
        //在起点和终点分别添加线的记录
        source._sourcelist.push(line);
        target._targetlist.push(line);
        //将线添加到画布中
        canvas.add(line);
      }
      var Circle1 = makeCircle(line.get("x1"), line.get("y1"), null, line);
      var Circle2 = makeCircle(
        line.get("x2"),
        line.get("y2"),
        line,
        line2,
        line5,
        line6
      );
      var Circle3 = makeCircle(
        line2.get("x2"),
        line2.get("y2"),
        line2,
        line3,
        line4
      );
      var Circle4 = makeCircle(line3.get("x2"), line3.get("y2"), line3);
      var Circle5 = makeCircle(line4.get("x2"), line4.get("y2"), line4);
      var Circle6 = makeCircle(line5.get("x2"), line5.get("y2"), line5);
      var Circle7 = makeCircle(line6.get("x2"), line6.get("y2"), line6);

      //   canvas.add(line, line2, line3, line4, line5, line6);
      canvas.add(Circle1, Circle2, Circle3, Circle4, Circle5, Circle6, Circle7);
      addline(Circle1, Circle2);
      //生成从minNum到maxNum的随机数
      function randomNum(minNum, maxNum) {
        switch (arguments.length) {
          case 1:
            return parseInt(Math.random() * minNum + 1, 10);
            break;
          case 2:
            return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
            break;
          default:
            return 0;
            break;
        }
      }
      for (let i = 0; i < 7; i++) {
        addline(
          eval("Circle" + randomNum(1, 7)),
          eval("Circle" + randomNum(1, 7))
        );
      }
      var panning = false;
      canvas.on("mouse:down", function(e) {
        //鼠标点击位置没有元素时拖动
        console.log(e)
        if (!e.target) {
          panning = true;
        }
      });
      //鼠标抬起
      canvas.on("mouse:up", function(e) {
        panning = false;
      });
      canvas.on("mouse:move", function(e) {
        if (panning && e && e.e) {
          var delta = new fabric.Point(e.e.movementX, e.e.movementY);
          canvas.relativePan(delta);
        }
      });
      canvas.on("object:moving", function(e) {
        var p = e.target;
        // p._sourcelist&&p._sourcelist.set({ x1: p.left, y1: p.top })
        // p._targetlist&&p._targetlist.set({ x2: p.left, y2: p.top })
        p._targetlist.forEach(function(item) {
          item.set({ x2: p.left, y2: p.top });
        });
        p._sourcelist.forEach(function(item) {
          item.set({ x1: p.left, y1: p.top });
        });
        // p.line1 && p.line1.set({ x2: p.left, y2: p.top });
        // p.line2 && p.line2.set({ x1: p.left, y1: p.top });
        // p.line3 && p.line3.set({ x1: p.left, y1: p.top });
        // p.line4 && p.line4.set({ x1: p.left, y1: p.top });
        canvas.renderAll();
      });
    });
  }
};
</script>

